/******************************************************************
 *  MRRM's ALU                                                    *
 *                                                                *
 *  This file is part of the MRRM project                         *
 *  <http://mrrm.googlecode.com/>                                 *
 *                                                                *
 *  Author(s):                                                    *
 *    -  Yuan Pengfei <coolypf@opencores.org>                     *
 *                                                                *
 ******************************************************************
 *                                                                *
 *  Copyright (C) 2010 AUTHORS                                    *
 *                                                                *
 *  This source file may be used and distributed without          *
 *  restriction provided that this copyright statement is not     *
 *  removed from the file and that any derivative work contains   *
 *  the original copyright notice and the associated disclaimer.  *
 *                                                                *
 *  MRRM is free software: you can redistribute it and/or modify  *
 *  it under the terms of the GNU General Public License as       *
 *  published by the Free Software Foundation, either version 3   *
 *  of the License, or (at your option) any later version.        *
 *                                                                *
 *  MRRM is distributed in the hope that it will be useful, but   *
 *  WITHOUT ANY WARRANTY; without even the implied warranty of    *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the  *
 *  GNU General Public License for more details.                  *
 *                                                                *
 *  You should have received a copy of the GNU General Public     *
 *  License along with MRRM. If not, see                          *
 *  <http://www.gnu.org/licenses/>.                               *
 *                                                                *
 ******************************************************************/

`include "global.v"

module mrrm_alu(
	// Operands
	op, a, b,
	// Results
	x, y,
	// Flags
	v, c, z, n
	);

parameter ow = `OPERAND_WIDTH;

// Interfaces
// Operands
input [2:0] op;
input [ow-1:0] a;
input [ow-1:0] b;

// Results
output [ow-1:0] x;
output [ow-1:0] y;

// Flags
output v;
output c;
output z;
output n;

// Internal wires and regs
wire signed [ow-1:0] sa;
wire signed [ow-1:0] sb;
reg [ow-1:0] x;
reg [ow-1:0] y;
reg v;
reg c;
reg z;
reg n;

// Signed conversion
assign sa = a;
assign sb = b;

// ALU execution
always @(op or a or b or sa or sb)
begin
	case(op)
		`ALU_ADD:    begin
			{c, x} = {1'b0, a} + {1'b0, b};
			y = 32'b0;
			z = (x == 32'b0) ? 1'b1 : 1'b0;
			n = x[31];
		end
		`ALU_SUB:    begin
			{c, x} = {1'b0, a} + {1'b0, ~b} + 1;
			y = 32'b0;
			z = (x == 32'b0) ? 1'b1 : 1'b0;
			n = x[31];
		end
		`ALU_AND:    begin
			x = a & b;
			y = 32'b0;
			c = 1'b0;
			z = (x == 32'b0) ? 1'b1 : 1'b0;
			n = x[31];
		end
		`ALU_OR:     begin
			x = a | b;
			y = 32'b0;
			c = 1'b0;
			z = (x == 32'b0) ? 1'b1 : 1'b0;
			n = x[31];
		end
		`ALU_MUL:    begin
			x = a * b;
			y = 32'b0;
			c = 1'b0;
			z = (x == 32'b0) ? 1'b1 : 1'b0;
			n = x[31];
		end
		`ALU_MULSL:  begin
			{y, x} = sa * sb;
			c = 1'b0;
			z = ({x, y} == 64'b0) ? 1'b1 : 1'b0;
			n = y[31];
		end
		`ALU_MOV:    begin
			x = b;
			y = 32'b0;
			c = 1'b0;
			z = (x == 32'b0) ? 1'b1 : 1'b0;
			n = x[31];
		end
		default:    begin
			x = a;
			y = 32'b0;
			c = 1'b0;
			z = (x == 32'b0) ? 1'b1 : 1'b0;
			n = x[31];
		end
	endcase
	v = ({a[31], b[31], x[31]} == 3'b100 || {a[31], b[31], x[31]} == 3'b011)
		? 1'b1 : 1'b0;
end

endmodule
